﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using EasyClassWEBAPI.EntityClass;
using EasyClassWEBAPI.Models;
using EasyClassWEBAPI.Utils;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Concurrent;

namespace EasyClassWEBAPI.Controllers
{
    [Route("Post")]
    [ApiController]
    public class PostController : ControllerBase
    {
        private EasyClassContext db;
        private readonly IWebHostEnvironment HostEnvironment;
        public PostController(EasyClassContext context,IWebHostEnvironment environment)
        {
            this.db = context;
            this.HostEnvironment = environment;
        }

        /// <summary>
        /// 添加一个新的帖子 Post：Post/add
        /// Annex:帖子的附件 IFormFile的格式与上传文件相同
        /// Annex里面要包含以日期命名的Post，DateTime.Now.ToString("yyyy-M-dd--HH-mm-ss")+".md"
        /// PostString：Post对象序列化为字符串String再进行传输[FormData Text格式]
        /// 注意：Header中需要包含Token来唯一标识建立帖子的用户
        /// Post里面必须包含Title,Category,StudyGroupID,CreateTime
        /// </summary>
        /// <param name="Annex"></param>
        /// <param name="postSting"></param>
        /// <returns></returns>
        [HttpPost("Add")]
        public async Task<IActionResult> AddPost([FromForm]IFormCollection Annex,[FromForm]string PostString)
        {
            try
            {
                String name = Annex.Files.Select(o => o.FileName).FirstOrDefault(o => PathManager.isContainPost(o));
                if (name == null) return BadRequest("You Should Upload the Post Firstly.");
                //获取Token标识的用户
                string token = this.Request.Headers["Authorization"];
                var user = await db.Users.FirstOrDefaultAsync(o => o.Token == token);
                if (user == null) return NotFound("User didn't exist!");

                //将String反序列化为Post
                Post post = TypeToString.StringToPost(PostString);
                post.User = user;
                db.Posts.Add(post);
                await db.SaveChangesAsync();//需要预先保存一次才会自动生成PostID

                //利用IWebHostEnvironment获取当前的路径
                string ContentRootPath = HostEnvironment.ContentRootPath;
                string ResourePath = PathManager.GetPath(ContentRootPath, post.PostID, false);

                var group = await db.StudyGroups.FirstOrDefaultAsync(o => o.StudyGroupID == post.StudyGroupID);

                //进行文件存储
                if (Annex.Files.Count>=1)
                {
                    foreach(var file in Annex.Files)
                    {
                        if(file.Length > 0)
                        {
                            //获取文件名
                            var filePath = file.FileName;
                            //创建文件流
                            using (FileStream fs = System.IO.File.Create(ResourePath + filePath))
                            {
                                await file.CopyToAsync(fs);
                            }
                            StudyResource resource = new StudyResource { FileName = filePath, FileSize = file.Length };
                            resource.Post = post;
                            resource.StudyGroup = group;
                            db.StudyResources.Add(resource);
                        }
                    }                   
                }
                await db.SaveChangesAsync();
                return Ok(post.PostID);
            }catch(Exception error)
            {
                return BadRequest($"Create post failed, reson:{error.Message}");
            }
        }
        
        /// <summary>
        /// 帖子点赞 Put:post/likeadd
        /// </summary>
        /// <param name="PostID"></param>
        /// <returns></returns>
        [HttpPut("LikeAdd")]
        public async Task<IActionResult> AddPostLike(int PostID)
        {
            try
            {
                Post post = await db.Posts.FirstOrDefaultAsync(o => o.PostID == PostID);
                post.LikeCount += 1;
                await db.SaveChangesAsync();
                return Ok("Add Like Count Successfully!");
            }catch(Exception error)
            {
                return BadRequest($"Add Like Count Failed. Reson:{error.Message}");
            }
        }

        /// <summary>
        /// 增加浏览数 Put:Post/ViewNumAdd
        /// </summary>
        /// <param name="PostID"></param>
        /// <returns></returns>
        [HttpPut("ViewNumAdd")]
        public async Task<IActionResult> AddPostViewNum(int PostID)
        {
            try
            {
                Post post = await db.Posts.FirstOrDefaultAsync(o => o.PostID == PostID);
                post.LookCount += 1;
                await db.SaveChangesAsync();
                return Ok("Add View Num Count Successfully!");
            }
            catch (Exception error)
            {
                return BadRequest($"Add View Num Count Failed. Reson:{error.Message}");
            }
        }

        /// <summary>
        /// 根据Title查询相关的帖子 Get:post/searchbytitles
        /// Title：用户输入的字符串
        /// StudyGroupID：是否在某一个具体的群里面查询，如果希望全局查询请置为-1
        /// n:需要返回的数目
        /// </summary>
        /// <param name="Title"></param>
        /// <param name="StudyGroupID"></param>
        /// <param name="n"></param>
        /// <returns></returns>
        [HttpGet("SearchByTitle")]
        public async Task<IActionResult> SearchByTitle(string Title,int StudyGroupID,int n)
        {
            try
            {
                //利用IWebHostEnvironment获取当前的路径
                string ContentRootPath = HostEnvironment.ContentRootPath;

                List<Post> posts = null;
                if (StudyGroupID != -1)
                    posts = await db.Posts
                        .Include(o =>o.StudyResources)
                        .Include(o=>o.User).Include(o=>o.Comments)
                        .Where(o => o.StudyGroupID == StudyGroupID).ToListAsync();
                else
                    posts = await db.Posts.Include(o => o.StudyResources).Include(o=>o.Comments)
                        .Include(o=>o.User).ToListAsync();

                ConcurrentBag<Post> res = null;
                if (Title == null)
                {
                    var tmp = posts.Take(n);
                    res = new ConcurrentBag<Post>(tmp);
                }
                else
                {
                    //获取所有Post的Title
                    IEnumerable<string> titlesOrigin = posts.Select(o => o.Title);
                    //转换为线程安全类
                    ConcurrentBag<string> titles = new ConcurrentBag<string>(titlesOrigin);
                    ConcurrentDictionary<string, double> similarity = new ConcurrentDictionary<string, double>();
                    //计算机相似度
                    //titles.ForEach(o => similarity[o] = SimilarityComputation.JaroWinklerMethod(Title, o));
                    Parallel.ForEach(titles, o => similarity[o] = SimilarityComputation.JaroWinklerMethod(Title, o));
                    //按照相似度降序排序（并取前几个）
                    var tmp = posts.OrderBy(o => similarity[o.Title]).Take(n);
                    res = new ConcurrentBag<Post>(tmp);
                }
                res.AsParallel().ForAll(o => {
                    //不可以把密码和Token返回给前端
                    o.User.Password = null;
                    o.User.Token = null;
                    string postPath = PathManager.GetPostPath(ContentRootPath, o.PostID, o.ContentName);
                    using (var fs = new FileStream(postPath,FileMode.Open,FileAccess.Read))
                    {
                        o.Content = StreamToBytes(fs);
                    }
                });
                return Ok(res);
            }catch(Exception error)
            {
                return BadRequest($"Search Posts By Titles Failed, Reson:{error.Message}");
            }
        }
        //将Stream转换为Byte
        private byte[] StreamToBytes(Stream stream)
        {
            byte[] bytes = new byte[stream.Length];
            stream.Read(bytes, 0, bytes.Length);

            // 设置当前流的位置为流的开始 
            stream.Seek(0, SeekOrigin.Begin);
            return bytes;
        }

        /// <summary>
        /// 返回指定用户加入群组最新发布的n个帖子 Get:post/return
        /// 注意需要在请求头中加入Token
        /// </summary>
        /// <param name="n"></param>
        /// <returns></returns>
        [HttpGet("Return")]
        public async Task<IActionResult> ReturnMostRecent(int n)
        {
            try
            {
                //利用IWebHostEnvironment获取当前的路径
                string ContentRootPath = HostEnvironment.ContentRootPath;

                //获取Token标识的用户
                string token = this.Request.Headers["Authorization"];
                var user = await db.Users.FirstOrDefaultAsync(o => o.Token == token);
                if (user == null) return NotFound("User didn't exist!");

                //获取该用户加入的所有小组
                var groupInfos = db.StudyGroups.Where(o =>o.Members.Contains(user.UserAccount));

                var posts = db.Posts.Include(o=>o.User).Include(o=>o.StudyResources).Include(o=>o.Comments)
                    .Where(o => groupInfos.Contains(o.StudyGroup)).OrderByDescending(o => o.CreateTime).Take(4);
                posts.AsParallel().ForAll(o=>{
                    o.User.Password = null;
                    o.User.Token = null;
                    o.User.Department = null;
                    o.User.StudyGroups = null;
                    if (o.StudyGroup!=null) o.StudyGroup = null;
                    string postPath = PathManager.GetPostPath(ContentRootPath, o.PostID, o.ContentName);
                    using (var fs = new FileStream(postPath, FileMode.Open, FileAccess.Read))
                    {
                        o.Content = StreamToBytes(fs);
                    }
                });
                return Ok(posts);
            }
            catch(Exception error)
            {
                return BadRequest($"Failed:{error.Message}");
            }
        }
        /// <summary>
        /// 查询一个用户所有的帖子 Get:post/searchbyuser
        /// </summary>
        /// <returns></returns>
        [HttpGet("SearchByUser")]
        public async Task<IActionResult> SearchByUser()
        {
            try
            {
                //利用IWebHostEnvironment获取当前的路径
                string ContentRootPath = HostEnvironment.ContentRootPath;
                //获取Token标识的用户
                string token = this.Request.Headers["Authorization"];
                var user = await db.Users.FirstOrDefaultAsync(o => o.Token == token);
                if (user == null) return NotFound("User didn't exist!");
                //查询该用户所有的帖子
                var posts = db.Posts.Include(o => o.User).Include(o=>o.Comments).Where(o => o.User == user);
                //删除一些不重要的信息
                posts.AsParallel().ForAll(o => {
                    o.User.Password = null;
                    o.User.Token = null;
                    o.User.Department = null;
                    o.User.StudyGroups = null;
                    if (o.StudyGroup != null) o.StudyGroup = null;
                    string postPath = PathManager.GetPostPath(ContentRootPath, o.PostID, o.ContentName);
                    using (var fs = new FileStream(postPath, FileMode.Open, FileAccess.Read))
                    {
                        o.Content = StreamToBytes(fs);
                    }
                });
                return Ok(posts);
            }catch(Exception error)
            {
                return BadRequest(error.Message);
            }
        }
    }
}
